package com.elitel.frame.base.service.impl;


import com.elitel.common.utils.UUIDUtil;
import com.elitel.frame.base.component.RedisCacheComponent;
import com.elitel.frame.base.service.AcStationPushRecordService;
import com.elitel.frame.base.service.SysPrjServiceService;
import com.elitel.frame.main.dao.*;
import com.elitel.frame.main.dao.ext.ExtSysPrjserviceMapper;
import com.elitel.frame.main.entity.*;
import com.elitel.frame.main.entity.acappcatalog.AcAppCatalog;
import com.elitel.frame.main.entity.acappcatalog.AcAppCatalogExample;
import com.elitel.frame.main.entity.acappstation.AcAppStation;
import com.elitel.frame.main.entity.acappstation.AcAppStationExample;
import com.elitel.frame.main.entity.constant.DictionaryConstant;
import com.elitel.frame.main.entity.constant.ServiceTypeConstant;
import com.elitel.frame.main.entity.constant.TmpUser;
import com.elitel.frame.main.entity.vo.AcStationPushRecordVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mulis
 */
@Service
public class AcStationPushRecordServiceImpl implements AcStationPushRecordService {
    @Autowired
    private RedisCacheComponent redisCacheComponent;
    @Autowired
    private AcStationPushRecordMapper acStationPushRecordMapper;
    @Autowired
    private AcAppMapper acAppMapper;
    @Autowired
    private SysPrjServiceService sysPrjServiceService;
    @Autowired
    private AcAppServiceMapper acAppServiceMapper;
    @Autowired
    private ExtSysPrjserviceMapper extSysPrjserviceMapper;
    @Autowired
    private AcAppCatalogMapper acAppCatalogMapper;
    @Autowired
    private AcAppStationMapper acAppStationMapper;
    @Autowired
    private CfgExtsqlMapper cfgExtsqlMapper;

    /**
     * 保存更新信息
     *
     * @param catalogList
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(List<AcAppCatalog> catalogList) {

        // 更新的分组id
        List<String> catalogIdList = catalogList.stream().map(AcAppCatalog::getCatalogId).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
        // 应用id
        List<String> appIdList = catalogList.stream().map(AcAppCatalog::getAppId).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());

        // 根据分组id查询到绑定的服务
        List<AcAppService> acAppServices = acAppServiceMapper.selectByCatalogIds(catalogIdList);
        List<String> serviceIds = acAppServices.stream().map(AcAppService::getServiceId).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
        List<SysPrjservice> sysPrjservices = extSysPrjserviceMapper.geServiceList(null, serviceIds);
        Map<String, SysPrjservice> idServiceMap = sysPrjservices.stream().collect(Collectors.toMap(SysPrjservice::getGuid, r -> r, (r1, r2) -> r1));

        // 查询应用信息
        List<AcApp> acAppList = acAppMapper.selectByPrimaryKeys(appIdList);
        Map<String, AcApp> idAppMap = acAppList.stream().collect(Collectors.toMap(AcApp::getAppId, r -> r, (r1, r2) -> r1));

        // 查询分组信息
        AcAppCatalogExample example = new AcAppCatalogExample();
        example.createCriteria().andCatalogIdIn(catalogIdList);
        List<AcAppCatalog> acAppCatalogs = acAppCatalogMapper.selectByExample(example);
        Map<String, AcAppCatalog> idCatalogMap = acAppCatalogs.stream().collect(Collectors.toMap(AcAppCatalog::getCatalogId, r -> r, (r1, r2) -> r1));

        // 封装数据
        ArrayList<AcStationPushRecord> insertData = new ArrayList<>();
        for (AcAppService i : acAppServices) {
            // 只封装绑定服务的数据
            AcStationPushRecord record = new AcStationPushRecord();
            SysPrjservice prjservice = idServiceMap.get(i.getServiceId());
            AcAppCatalog acAppCatalog = idCatalogMap.get(i.getFilterCatalogId());
            AcApp acApp = idAppMap.get(i.getAppId());
            if (prjservice == null || acAppCatalog == null || acApp == null) {
                continue;
            }

            // 服务信息
            record.setServiceName(prjservice.getServicename());
            record.setServiceCode(prjservice.getServicecode());
            // 分类信息
            record.setCatalogName(acAppCatalog.getCatalogName());
            // 调用方信息
            record.setAppCode(acApp.getAppCode());
            record.setAppName(acApp.getAppName());
            record.setCatalogId(i.getFilterCatalogId());
            insertData.add(record);
        }


        List<String> catalogIds = insertData.stream().map(AcStationPushRecord::getCatalogId).collect(Collectors.toList());
        
        if (CollectionUtils.isNotEmpty(catalogIds)) {
            AcStationPushRecord dto = new AcStationPushRecord();
            dto.setCatalogIdList(catalogIds);
            // 分组id拿到记录
            acStationPushRecordMapper.deleteByCatalogIds(dto);
        }
    
        Date date = new Date();
        for (AcStationPushRecord record : insertData) {
            // 如果之前分组有在记录表里面插入数据就更新, 没有就新增
                record.setPushRecordId(UUIDUtil.randomUUID());
                record.setRevision(date.getTime() + "");
                record.setStatus(DictionaryConstant.NO);
                record.setCreatedTime(date);
                record.setCreatedUser(TmpUser.ADMIN);
                record.setUpdatedTime(date);
                record.setUpdatedUser(TmpUser.ADMIN);
                acStationPushRecordMapper.insertSelective(record);
        }

    }



    /**
     * 执行定时任务
     */
    @Override
    public List<AcStationPushRecordVO> getPushData() {

        AcStationPushRecord dto = new AcStationPushRecord();
        dto.setStatus(DictionaryConstant.NO);
        // 拿到更新过的分组
        List<AcStationPushRecord> resList = acStationPushRecordMapper.selectList(dto);
        
        if (CollectionUtils.isEmpty(resList)) {
            return new ArrayList<>();
        }

        // 根据分组拿到绑定的测站信息
        List<String> catalogIdList = resList.stream().map(AcStationPushRecord::getCatalogId).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
        AcAppStationExample acAppStationExample = new AcAppStationExample();
        acAppStationExample.createCriteria().andCatalogIdIn(catalogIdList);
        List<AcAppStation> acAppStations = acAppStationMapper.selectByExample(acAppStationExample);
        Map<String, List<AcAppStation>> catalogIdStationMap = acAppStations.stream().collect(Collectors.groupingBy(AcAppStation::getCatalogId));

        // 查询项目基本信息
        List<String> serviceCodes = resList.stream().map(AcStationPushRecord::getServiceCode).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
        List<SysPrjservice> byServiceCodes = sysPrjServiceService.getByServiceCodes(serviceCodes);
        Map<String, String> codeGuidMap = byServiceCodes.stream().collect(Collectors.toMap(SysPrjservice::getServicecode, SysPrjservice::getGuid, (r1, r2) -> r1));
        List<String> serviceIds = byServiceCodes.stream().map(SysPrjservice::getGuid).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());

        // 查询项目下的分组信息
        List<AcAppService> acAppServices = acAppServiceMapper.selectByServiceIds(serviceIds);
        Map<String, List<AcAppService>> serviceIdAppCatalogMap = acAppServices.stream().collect(Collectors.groupingBy(AcAppService::getServiceId));
        
        // 查询应用信息
        List<AcApp> acAppList = acAppMapper.selectByPrimaryKeys(acAppServices.stream().map(AcAppService::getAppId).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList()));
        Map<String, AcApp> idAppMap = acAppList.stream().collect(Collectors.toMap(AcApp::getAppId, r -> r, (r1, r2) -> r1));

        // 根据分类查询数据库连接信息
        Map<String, List<SysPrjservice>> typeMap = byServiceCodes.stream().collect(Collectors.groupingBy(SysPrjservice::getServicetype));
        HashMap<String, String> servcieCodeCfgExtendHashMap = new HashMap<>();
        for (String serviceType : typeMap.keySet()) {
            List<SysPrjservice> sysPrjservices = typeMap.get(serviceType);
            List<String> serviceCodeList = sysPrjservices.stream().map(SysPrjservice::getServicecode).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
            switch (serviceType) {

                case ServiceTypeConstant.SINGLE_TABLE_SERVER:
                    Map<String, String> stringCfgExtendMap = redisCacheComponent.selectDbKeyByServiceCodes(serviceCodeList);
                    servcieCodeCfgExtendHashMap.putAll(stringCfgExtendMap);
                    break;
                case ServiceTypeConstant.EXECUTE_SQL_SERVER:
                    List<CfgExtsql> cfgExtsqls = cfgExtsqlMapper.selectByPrimaryKeyList(serviceCodeList);
                    Map<String, String> codeExtMap = cfgExtsqls.stream().collect(Collectors.toMap(CfgExtsql::getGuid, CfgExtsql::getDtDbKey, (r1, r2) -> r1));
                    servcieCodeCfgExtendHashMap.putAll(codeExtMap);
                    break;
                default:
            }
        }

        // 服务的数据源信息
        HashMap<String, CfgDb> serviceCodeCfgDbMap = new HashMap<>(servcieCodeCfgExtendHashMap.keySet().size());
        for (String serviceCode : servcieCodeCfgExtendHashMap.keySet()) {
            String dbKey = servcieCodeCfgExtendHashMap.get(serviceCode);
            // 缓存可以循环
            CfgDb cfgDB = redisCacheComponent.cfgDBRedisCache(dbKey);
            serviceCodeCfgDbMap.put(serviceCode, cfgDB);

        }

        // 封装推送数据
        List<AcStationPushRecordVO> acStationPushRecordVOS = new ArrayList<>();
        for (AcStationPushRecord record : resList) {
            AcStationPushRecordVO item = new AcStationPushRecordVO();
            item.setPushRecordId(record.getPushRecordId());
            String serviceCode = record.getServiceCode();
            String serviceId = codeGuidMap.get(serviceCode);
            // 分组信息
            List<AcAppService> acAppServicesList = serviceIdAppCatalogMap.get(serviceId);
            if (CollectionUtils.isEmpty(acAppServicesList)) {
                continue;
            }
            List<AcStationPushRecordVO.PushData> objects = new ArrayList<>();
            for (AcAppService acAppService : acAppServicesList) {

                AcStationPushRecordVO.PushData pushData = new AcStationPushRecordVO.PushData();
                pushData.setServiceCode(serviceCode);
                pushData.setCfgdb(serviceCodeCfgDbMap.get(serviceCode));
                AcApp acApp = idAppMap.get(acAppService.getAppId());
                String appCode = acApp == null ? "" : acApp.getAppCode();
                pushData.setAppCode(appCode);
              
                // 分组测站信息
                String filterCatalogId = acAppService.getFilterCatalogId();
                List<AcAppStation> acAppStationsList = catalogIdStationMap.get(filterCatalogId);
                // 为空 则证明当前分组没有做更新  下一个
                // if (CollectionUtils.isEmpty(acAppStationsList)) continue;
                if (acAppStationsList == null) {
                    acAppStationsList = new ArrayList<>();
                }
                
                List<AcFilterStation> acFilterStations = new ArrayList<>();
                for (AcAppStation acAppStation : acAppStationsList) {
                    AcFilterStation acFilterStation = new AcFilterStation();
                    acFilterStation.setDataId(UUIDUtil.randomUUID());
                    acFilterStation.setServiceId(serviceId);
                    acFilterStation.setStcd(acAppStation.getStcd());
                    acFilterStation.setAppCode(appCode);
                    acFilterStations.add(acFilterStation);
                }
                pushData.setAcFilterStationList(acFilterStations);
                objects.add(pushData);
            }
            item.setPushDataList(objects);
            acStationPushRecordVOS.add(item);
        }
        return acStationPushRecordVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateList(List<AcStationPushRecord> list) {
        if (CollectionUtils.isEmpty(list)) {
            return 0;
        }
        Date date = new Date();
        // 有时间再实现
//       return acStationPushRecordMapper.batchUpdate(list);
        AcStationPushRecord dto = new AcStationPushRecord();
        dto.setStatus(DictionaryConstant.NO);
        List<AcStationPushRecord> resList = acStationPushRecordMapper.selectList(dto);
        Map<String, String> idLockMap = resList.stream().collect(Collectors.toMap(AcStationPushRecord::getPushRecordId, AcStationPushRecord::getRevision));
        for (AcStationPushRecord record : list) {
            record.setRevision(idLockMap.get(record.getPushRecordId()));
            record.setUpdatedUser(TmpUser.ADMIN);
            record.setUpdatedTime(date);
            acStationPushRecordMapper.updateByPrimaryKeyAndLock(record);
        }
        return list.size();
    }


}
